package com.zhima.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zhima.dto.FeignDownloadResultDTO;
import com.zhima.dto.FeignUploadResultDTO;
import com.zhima.entity.OjFile;
import com.zhima.entity.ZhimaMinioUploadFileResponse;
import com.zhima.exception.ZhimaMinioException;
import com.zhima.exception.ZhimaOjException;
import com.zhima.mapper.OjFileMapper;
import com.zhima.service.OjFileService;
import com.zhima.service.ZhimaMinioService;
import com.zhima.util.UserHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Date;

import static com.zhima.exception.ErrorCode.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zhima
 * @since 2023-08-25
 */
@Slf4j
@Service
public class OjFileServiceImpl extends ServiceImpl<OjFileMapper, OjFile> implements OjFileService {
    @Autowired
    private ZhimaMinioService zhimaMinioService;

    @Override
    public FeignUploadResultDTO uploadFile(Long uploaderId, String bucket, String fileName, byte[] bytes) {
        try {
            return saveFileInfo(uploaderId, zhimaMinioService.uploadFile(bucket, fileName, bytes));
        } catch (Exception e) {
            throw new ZhimaOjException(e, UPLOAD_FILE_FAILURE);
        }
    }

    private FeignUploadResultDTO saveFileInfo(ZhimaMinioUploadFileResponse response) {
        return saveFileInfo(UserHolder.get().getId(), response);
    }

    private FeignUploadResultDTO saveFileInfo(Long uploaderId, ZhimaMinioUploadFileResponse response) {
        OjFile ojFile = new OjFile();
        ojFile.setBucket(response.getBucket());
        // 原文件名
        ojFile.setFileName(response.getFileName());
        ojFile.setSize(response.getFileSize());
        ojFile.setUploadTime(new Date());
        ojFile.setUploadUserId(uploaderId);
        // 文件的uri不包括桶名
        ojFile.setUri(response.getPathWithOutBucket());
        // 文件的md5值
        ojFile.setFileMd5(response.getFileMd5());
        save(ojFile);
        FeignUploadResultDTO feignUploadResultDTO = new FeignUploadResultDTO();
        feignUploadResultDTO.setFileId(ojFile.getId());
        feignUploadResultDTO.setPathWithBucket(response.getPathWithBucket());
        feignUploadResultDTO.setFileSize(response.getFileSize());
        return feignUploadResultDTO;
    }

    @Override
    public FeignUploadResultDTO uploadFile(String bucket, String fileAbsolutePath) {
        try {
            return saveFileInfo(zhimaMinioService.uploadFile(bucket, fileAbsolutePath));
        } catch (Exception e) {
            throw new ZhimaOjException(e, UPLOAD_FILE_FAILURE);
        }
    }

    @Override
    public FeignUploadResultDTO mergeChunk(String bucket, String fileMd5, String chunkFileName, Integer chunkSize) {
        try {
            return saveFileInfo(zhimaMinioService.mergeChunk(bucket, fileMd5, chunkFileName, chunkSize));
        } catch (Exception e) {
            throw new ZhimaOjException(e, MERGE_CHUNK_FILE_FAILURE);
        }
    }

    @Override
    public boolean checkChunk(String bucket, String fileMd5, Integer chunkIndex) {
        try {
            return zhimaMinioService.checkChunk(bucket, fileMd5, chunkIndex);
        } catch (ZhimaMinioException e) {
            throw new ZhimaOjException(e, MINIO_CONNECT_FAILURE);
        }
    }

    @Override
    public boolean existsFile(String bucket, String objectName) {
        try {
            return zhimaMinioService.existsFile(bucket, objectName);
        } catch (ZhimaMinioException e) {
            throw new ZhimaOjException(e, MINIO_CONNECT_FAILURE);
        }
    }

    @Override
    public byte[] download(String bucket, String objectName) {
        try {
            return zhimaMinioService.download(bucket, objectName);
        } catch (ZhimaMinioException e) {
            throw new ZhimaOjException(e, DOWNLOAD_FILE_FAILURE);
        }
    }

    @Override
    public FeignDownloadResultDTO downloadByFileId(Long fileId) {
        OjFile ojFile = getById(fileId);
        byte[] bytes = download(ojFile.getBucket(), ojFile.getUri());
        FeignDownloadResultDTO feignDownloadResultDTO = new FeignDownloadResultDTO();
        feignDownloadResultDTO.setBytes(bytes);
        return feignDownloadResultDTO;
    }

    @Override
    public FeignDownloadResultDTO downloadByObjectId(String objectId) {
        // /testcases/2023/09/10/9dc9a6a4ad28abdf5d624113d486c29c.zip
        int index = objectId.indexOf('/', 1);
        byte[] bytes = download(objectId.substring(1, index), objectId.substring(index));
        FeignDownloadResultDTO feignDownloadResultDTO = new FeignDownloadResultDTO();
        feignDownloadResultDTO.setBytes(bytes);
        return feignDownloadResultDTO;
    }

    @Override
    public void deleteFileByFileId(Long fileId) {
        OjFile one = lambdaQuery().eq(OjFile::getId, fileId).select(OjFile::getBucket, OjFile::getUri).one();
        try {
            zhimaMinioService.deleteFile(one.getBucket(), one.getUri());
            removeById(fileId);
        } catch (ZhimaMinioException e) {
            throw new RuntimeException(e);
        }
    }
}
